/**
 * 
 */
package com.yullage.ae.util;

import java.io.FileReader;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import au.com.bytecode.opencsv.CSVReader;

import com.yullage.ae.core.Mind;

/**
 * @author Yu-chun Huang
 * 
 */
public class MindScriptPlayer {
	/**
	 * Logger
	 */
	private static final Logger logger = LoggerFactory
			.getLogger(MindScriptPlayer.class);

	private Mind mind;
	private List<Map<String, Double>> triggerList;

	public void load(Mind mind, String scriptFileName) throws IOException,
			Exception {
		this.mind = mind;
		triggerList = new ArrayList<Map<String, Double>>();

		logger.info("Load script file: {}.", scriptFileName);

		CSVReader reader = new CSVReader(new FileReader(scriptFileName));
		String[] nextLine;
		int numColumns = 0;

		while ((nextLine = reader.readNext()) != null) {
			numColumns = nextLine.length;
			if (numColumns == 0) {
				continue;
			}

			Map<String, Double> triggerValues = new HashMap<String, Double>();
			for (int i = 1; i < numColumns; i++) {
				String[] entry = nextLine[i].split("=");
				triggerValues.put(entry[0].toUpperCase(),
						Double.parseDouble(entry[1]));
			}

			int timeLength = Integer.parseInt(nextLine[0]);
			for (int i = 0; i < timeLength; i++) {
				triggerList.add(triggerValues);
			}

			logger.debug("Time length: {};  Trigger values: {}", timeLength,
					triggerValues.toString());
		}
	}

	public void runScript(int recordInterval, OutputStream outputStream)
			throws IOException {
		MindRecorder mindRecorder = new MindRecorder(mind);
		Map<String, Double> triggerValues;
		int totalThinkTime = triggerList.size();
		int curThinkTime;

		logger.info("Running mind script...");

		// Think Time = 0
		triggerValues = triggerList.get(0);

		for (Map.Entry<String, Double> entry : triggerValues.entrySet()) {
			mind.trigger(entry.getKey(), entry.getValue());
		}
		mindRecorder.displayText(outputStream);

		// Think Time >= 1
		for (curThinkTime = 1; curThinkTime < totalThinkTime; curThinkTime++) {
			triggerValues = triggerList.get(curThinkTime);

			mind.think(1);

			for (Map.Entry<String, Double> entry : triggerValues.entrySet()) {
				mind.trigger(entry.getKey(), entry.getValue());
			}

			if (curThinkTime % recordInterval == 0) {
				mindRecorder.displayText(outputStream);
			}
		}

		if ((totalThinkTime - 1) % recordInterval != 0) {
			mindRecorder.displayText(outputStream);
		}

		logger.info("Mind script completed.");
	}

	public void runScript(int recordInterval, String outputFileName)
			throws IOException {
		MindRecorder mindRecorder = new MindRecorder(mind);
		Map<String, Double> triggerValues;
		int totalThinkTime = triggerList.size();
		int curThinkTime;

		logger.info("Running mind script...");

		mindRecorder.resetRecords();

		// Think Time = 0
		triggerValues = triggerList.get(0);
		for (Map.Entry<String, Double> entry : triggerValues.entrySet()) {
			mind.trigger(entry.getKey(), entry.getValue());
		}
		mindRecorder.record();

		// Think Time >= 1
		for (curThinkTime = 1; curThinkTime < totalThinkTime; curThinkTime++) {
			triggerValues = triggerList.get(curThinkTime);

			mind.think(1);

			for (Map.Entry<String, Double> entry : triggerValues.entrySet()) {
				mind.trigger(entry.getKey(), entry.getValue());
			}

			if (curThinkTime % recordInterval == 0) {
				mindRecorder.record();
			}
		}

		if ((totalThinkTime - 1) % recordInterval != 0) {
			mindRecorder.record();
		}

		mindRecorder.writeRecords(outputFileName);

		logger.info("Mind script completed. Output file name: {}",
				outputFileName);
	}
}
